package com.yang.bean.beanfactory.impl;

import com.yang.bean.beanDefinition.BeanDefinition;
import com.yang.bean.beanfactory.BeanFactory;
import com.yang.bean.beanfactory.registry.impl.DefinitionSingletonBeanRegistry;
import org.apache.commons.lang3.ObjectUtils;

/**
 * @Description: 顶级接口的抽象实现类, 可以管理全局
 * @author: Yang Qiang
 * @create: 2021-11-07 17:54
 */
public abstract class AbstractBeanFactory extends DefinitionSingletonBeanRegistry implements BeanFactory {

    /**
     * 获得一个bean, 先从缓存中获取, 没有的话, 我们再创建
     * @param beanName
     * @return
     */
    @Override
    public Object getBean(String beanName) {
        Object singletonBean = getSingletonBean(beanName);

        // 缓存获取到了对象, 执行返回
        if (! ObjectUtils.isEmpty(singletonBean)){
            return singletonBean;
        }

        // 先根据bean获取BeanDefinition对象
        BeanDefinition beanDefinition = getBeanDefinition(beanName);

        // 然后根据BeanDefinition对象来创建bean对象, 如果是多例的话直接创建, 如果是单例的话可以放进缓存中
        if (beanDefinition.isSingleton()){
            // 单例
            // 创建对象
            singletonBean = createBean(beanDefinition);

            // 注册对象
            registrySingletonBean(beanName, singletonBean);

        }else if (beanDefinition.isPrototype()){
            // 多例/原型, 直接创建对象, 因为不需要缓存
            singletonBean = createBean(beanDefinition);
        }

        return singletonBean;
    }

    /**
     * 创建一个bean对象, 根据BeanDefinition创建
     * @param beanDefinition
     * @return
     */
    protected abstract Object createBean(BeanDefinition beanDefinition);

    /**
     * 获取bean, 这个获取BeanDefinition对象的方法, 我们创建为抽象方法
     * 然后继承这个抽象类的实现类, 就必须实现这个方法, 然后可以进行扩展
     * @param beanName
     * @return
     */
    protected abstract BeanDefinition getBeanDefinition(String beanName);
}
